#ifndef __WORLD_H__
#define __WORLD_H__
#include <vector>
#include "Command.h"
#include "Graph.h"
#include "Vector2.h"

struct constant_t;
struct flag_t;
struct tank_t;
struct obstacle_t;
struct otank_t;
struct shot_t;
struct team_t;
struct occgrid_t;
class KalmanTank;
class KalmanFilter;
class KalmanObstacle;
class Track;

using std::vector;

class World
{
public:
	static World* instance();
	~World();

	void init();

	Command update();

	vector <constant_t> & constants();
	vector <flag_t> & flags();
	vector <tank_t> & tanks();
	vector <obstacle_t> & obstacles();
	vector <otank_t> & other_tanks();
	vector <shot_t> & shots();
	vector <team_t> & teams();
	vector <occgrid_t> & occgrids();
	vector <KalmanTank> & enemies();
	vector <KalmanObstacle> & kobstacles();

	vector <constant_t> * constantsP();
	vector <flag_t> * flagsP();
	vector <tank_t> * tanksP();
	vector <obstacle_t> * obstaclesP();
	vector <otank_t> * other_tanksP();
	vector <shot_t> * shotsP();
	vector <team_t> * teamsP();
	vector <occgrid_t> * occgridsP();
	vector <KalmanTank> * enemiesP();
	vector <KalmanObstacle> * kobstaclesP();

	int getSize();
	Graph* getGraph();
	Vector2 getFlagPos(string flag_color);
	Vector2 getBasePos(string base_color);
	float getTruePositive();
	float getTrueNegative();
	int getBulletSpeed();
	int getShotRange();
	string getTeam();
	void updateKalmanFilters();

	bool intersectsAnObstacle(Vector2 & start, Vector2 & end);

	bool TeamMemberHasFlag();

	void flagBearerDir(Vector2 newDir);
	Vector2 flagBearerDir();

	void flagBearer(tank_t* tank);
	tank_t* flagBearer();

	bool blocked(Vector2 & start, Vector2 & end);

private:
	World();
	
	bool linesIntersect(Vector2 & start, Vector2 & end, Vector2 & ob_start, Vector2 & ob_end);
	void updateKalmanFilter(KalmanFilter & filter);


	static World* _instance;

	vector <constant_t> _constants;
	vector <flag_t> _flags;
	vector <tank_t> _tanks;
	vector <obstacle_t> _obstacles;
	vector <otank_t> _other_tanks;
	vector <shot_t> _shots;
	vector <team_t> _teams;
	vector <occgrid_t> _occgrids;

	vector <KalmanTank> _enemies;
	vector <KalmanObstacle> _kobstacles;

	Graph* graph;

	int size;
	float truePositive;
	float trueNegative;
	int bulletSpeed;
	int shotRange;

	string team;

	Vector2 _flagBearerDir;
	tank_t* _flagBearer;
};

#endif